/*!
 * ol3地图基本函数
 * 当前版本：1.1
 * 创建人：雷志强
 * 创建时间：20180715
 * 需要引用jquery.js脚本库配合使用
 * 1.1版本更新说明：
 * 20181009:将原来GPS历史轨迹修改成边走边显示线路，同时显示GPS时间.
 */

//定义测量工具提示框样式
document.write("<style type='text/css'>.hidden{display: none;}.tooltip {position: relative;background: rgba(0, 0, 0, 0.5);border-radius: 4px;color: white;padding: 4px 8px;opacity: 0.7;white-space: nowrap;}.tooltip-measure {opacity: 1;font-weight: bold;}.tooltip-static {background-color: #ffcc33;color: black;border: 1px solid white;}.tooltip-measure:before,.tooltip-static:before {border-top: 6px solid rgba(0, 0, 0, 0.5);border-right: 6px solid transparent;border-left: 6px solid transparent;content:'';position: absolute;bottom: -6px;margin-left: -7px;left: 50%;}.tooltip-static:before {border-top-color: #ffcc33;}</style>");
window.olMap = window.olMap || {};
window.olMap = {
	//定义对象别名
	_this:this,
	//地图对象
	map:null,
	//地图图层对象
	mapLayers:[],
	//地图控件-鼠标位置显示控件
	mousePositionControl:null,
	//地图控件-地图比例尺控件
	scaleLineControl:null,
	gpsdata:[],
	//历史GPS信息
	gpshistory:{},
	//GPS轨迹点间隔距离1米，按1米进行加密
	gps_point_distance:5,
	//实时GPS信息
	gpsreal:{},
	//地球半径(单位：公里)
	EARTH_RADIUS:6378.137,
	//定义球体对象
	wgs84Sphere:new ol.Sphere(6378137),
	//定义测量对象，存储相关对象
	measure:{},
	//用户交互操作对象
	drawinfo:{},
	//单个标注气泡对象，永远只显示一个气泡提示框
	onePopup:null,
	//要素交互绘制对象
	featureDraw:null,
	//要素绘制矢量图层对象
	drawLayer:null,
	/**
	 * 获取dom的样式值
	 * @param {Object} dom
	 * @param {Object} attr
	 */
	getDomStyle:function(dom, attr){
	  return dom.currentStyle ? dom.currentStyle[attr] : getComputedStyle(dom, false)[attr];
	},
	/**
	 * 角度转弧度，例如：rad(45)=0.7583
	 * @param {Number} d 角度，例如：30
	 */
	rad:function(d){
		return d * Math.PI / 180.0;
	},
	/**
	 * 计算两个坐标之间的距离(单位：米)，例如：getDistance(113.32,30.23,114.425,31.324)=161243米
	 * @param {Number} x1 第一个坐标点X坐标，例如：113.32
	 * @param {Number} y1 第一个坐标点Y坐标，例如：30.23
	 * @param {Number} x2 第二个坐标点X坐标，例如：114.425
	 * @param {Number} y2 第二个坐标点Y坐标，例如：31.324
	 * @return 两点的直线距离(单位：米)
	 */
	getDistance:function(x1,y1,x2,y2){
		var radLat1 = this.rad(y1);
	    var radLat2 = this.rad(y2);
	    var a = radLat1 - radLat2;
	    var b = this.rad(x1) - this.rad(x2);
	    var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) + Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
	    s = s * this.EARTH_RADIUS;
	    s = parseInt(1000*Math.round(s * 10000)/10000);
	    return s;
	},
	/**
	 * 获取两个点组成的线段与水平面的角度,例如：olMap.getPointAngle(113.32,30.23,114.425,31.324)=44.7133
	 * @param {Number} x1 第一个坐标点X坐标，例如：113.32
	 * @param {Number} y1 第一个坐标点Y坐标，例如：30.23
	 * @param {Number} x2 第二个坐标点X坐标，例如：114.425
	 * @param {Number} y2 第二个坐标点Y坐标，例如：31.324
	 */
	getPointAngle:function(x1,y1,x2,y2){
		var dx = parseFloat(x2) - parseFloat(x1);
		var dy = parseFloat(y2) - parseFloat(y1);
		var angle = 0;
		if(dx==0&&dy>0){//如果坐标X差为0，坐标Y差大于0 ，则角度为90度
			angle = 90;
		}else if(dx==0&&dy<0){
			angle = 270;
		}else if(dx!=0){
			angle=Math.atan(dy/dx)*180/Math.PI;
            if(dx<0&&dy==0){angle=180;}
            else if(dx>0&&dy==0){angle=0;}
            else if(dx>0&&dy>0){angle=angle;}
            else if(dx<0&&dy>0){angle=180*1+angle;}
            else if(dx<0&&dy<0){angle=180*1+angle;}
            else if(dx>0&&dy<0){angle=360*1+angle;}
		}
		return angle;
	},
	/**
	 * 将多个坐标点按指定距离进行加密(两个点按等距离生成更多的点)
	 * @param {Object} points，坐标点数组，例如：[{x:113,y:30},{x:114,y:31}]
	 * @param {Object} distance 需要将点加密的步长距离(单位：米)，例如：2
	 */
	getMorePointsByDistance:function(points,distance){
		var newPoints = new Array();
    	var pntCount = points.length;
    	var point1 = null;
    	var point2 = null;
    	for(var i=0;i<pntCount-1;i++){
    		point1 = points[i];
    		point2 = points[i+1];
    		//计算两个点的距离
    		var pntDistance = this.getDistance(point1.x,point1.y,point2.x,point2.y);
    		//根据点之间的距离计算两个点之间要生成多少个点
    		var count = parseInt(pntDistance/distance);
    		//计算两个点的X坐标差
    		var xdis = point2.x-point1.x;
    		//计算两个点的Y坐标差
	    	var ydis = point2.y-point1.y;
	    	//计算加密后的每一个点的X值步长
	    	var posx = xdis/count;
	    	//计算加密后的每一个点的Y值步长
	    	var posy = ydis/count;
	    	for(var k=0;k<count;k++){
	    		var px = point1.x+posx*k;
	    		var py = point1.y+posy*k;
	    		newPoints.push({x:px,y:py});
	    	}
    	}
    	return newPoints;
	},
	/**
	 * 将坐标点字符串转换坐标对象数组[{x:113,y:30.34}]
	 * @param {String} points 坐标点字符串，例如：113.32,30.345;113.56,30.64
	 * @return 坐标对象数组，例如：[{x:113.32,y:30.345},{x:113.56,y:30.64}]
	 */
	pointstrToPointArray:function(points){
		var pointArr = [];
		if(points!=null && points!=""){
			var strArr = points.split(";");
			var x = 0.0;
			var y = 0.0;
			for(var i=0;i<strArr.length;i++){
				x = parseFloat(strArr[i].split(",")[0]);
				y = parseFloat(strArr[i].split(",")[1]);
				pointArr.push({x:x,y:y});
			}
		}
		return pointArr;
	},
	/**
	 * 将坐标点字符串转成地图geom坐标
	 * @param {String} points 坐标点字符串，例如：113.32,30.345;113.56,30.64
	 * @return geom坐标数组，例如：[[113.32,30.345],[113.56,30.64]]
	 */
	pointstrToGeomPoint:function(points){
		var geomPoints = [];
		if(points!=null && points!=""){
			var strArr = points.split(";");
			var x = 0.0;
			var y = 0.0;
			for(var i=0;i<strArr.length;i++){
				x = parseFloat(strArr[i].split(",")[0]);
				y = parseFloat(strArr[i].split(",")[1]);
				geomPoints.push([x,y]);
			}
		}
		return geomPoints;
	},
	/**
	 * 将坐标点对象数组转换成地图geom坐标
	 * @param {Object} pointArray 坐标数组，例如：[{x:113.32,y:30.235},{x:113.574,30.415}]
	 * return geom坐标数组，例如：[[113.32,30.345],[113.56,30.64]]
	 */
	pointArrayToGeomPoint:function(pointArray){
		var geomPoints = [];
		if(pointArray!=null && pointArray.length>0){
			for(var i=0;i<pointArray.length;i++){
				geomPoints.push([pointArray[i].x,pointArray[i].y]);
			}
		}
		return geomPoints;
	},
	/**
	 * 获取多个点的外包矩形范围，返回值：{xmin:***,ymin:**,xmax:***,ymax:**,cx:***,cy:***}
	 * 20180828 雷志强
	 * @param {Object} pointArray 坐标数组，例如：[{x:113.32,y:30.235},{x:113.574,y:30.415}]
	 */
	getPointsRect:function(pointArray){
		var count = pointArray.length;
		var xmin = ymin = xmax = ymax = 0.0;
		var px = py = 0.0;
		for(var i=0;i<count;i++){
			px = pointArray[i].x;
			py = pointArray[i].y;
			if(i==0){
				xmin = xmax = px;
				ymin = ymax = py;
			}else{
				if(px < xmin){
					xmin = px;
				}else if(px > xmax){
					xmax = px;
				}
				if(py < ymin){
					ymin = py;
				}else if(py > ymax){
					ymax = py;
				}
			}
		}
		var cx = (xmin + xmax)/2;
		var cy = (ymin + ymax)/2;
		return {xmin:xmin,ymin:ymin,xmax:xmax,ymax:ymax,cx:cx,cy:cy};
	},
	/**
	 * 默认矢量线样式
	 */
	defaultVectorStyle:new ol.style.Style({
        //填充色
        fill: new ol.style.Fill({
            color: 'rgba(255, 255, 255, 0.2)'
        }),
        //边线颜色
        stroke: new ol.style.Stroke({
            color: '#4C8BF5',
            width: 2
        }),
        //形状
        image: new ol.style.Circle({
            radius: 10,
            fill: new ol.style.Fill({
                color: '#ffcc33'
            })
        })
    }),
    /**
     * 将已经初始化的地图对象设置给olMap的地图对象map
     * @param {Object} _map
     */
    setMap:function(_map){
    	this.map = _map;
    },
	/**
	 * 初始化地图容器
	 * @param {String} mapid 地图容器ID
	 * @param {Object} options 地图初始化参数对象{projection:"EPSG:4326",maxZoom:20,minZoom:1,zoom:3}
	 */
	initMap:function(mapid,options){
		//2018-11-23雷志强修改，增加地图初始化参数设置
		var viewOption = {};
		if(options != null){
			$.extend(true, viewOption, options);
		}
		var mapOption = {
			//地图窗口id
            target:mapid
		};
		if(JSON.stringify(viewOption)!="{}"){
			 //地图视图
			mapOption.view = new ol.View(viewOption);
		}
		console.log(mapOption);
		//初始化地图对象
		this.map = new ol.Map(mapOption);
        /**2018-11-23雷志强修改前备份
		var projection = 'EPSG:4326';
		var maxZoom = 20;
		var minZoom = 1;
		var zoom = 1;
		if(options!=null){
			if('projection' in options){
				projection = options.projection;
			}
			if('maxZoom' in options){
				maxZoom = options.maxZoom;
			}
			if('minZoom' in options){
				minZoom = options.minZoom;
			}
			if('zoom' in options){
				zoom = options.zoom;
			}
		}
		//初始化地图对象
		this.map = new ol.Map({
            //地图窗口id
            target:mapid,
            //地图视图
            view: new ol.View({
            	//投影方式
                projection: projection,
                //最大显示级数
                maxZoom: maxZoom,
                //最小显示级数
                minZoom: minZoom,
                //当前显示级数
                zoom: zoom
            })
        });
        */
	},
	/**
	 * 地图控件-添加鼠标位置控件到地图上.
	 * 20180823 雷志强
	 * @param {Object} divid 鼠标位置信息DIV窗口ID，例如:mouse-position
	 * @param {Object} projection 位置坐标投影转换参数，例如：EPSG:4326（默认wgs84坐标系统）
	 * @param {Object} numpos 坐标保留小数位数，例如：4，则显示113.2351
	 */
	addMousePositionControl:function(divid,projection,numpos){
		if(this.mousePositionControl!=null){
			return;
		}
		var _divid = "mouse-position";
		var _projection = "EPSG:4326";
		var _numpos = 4;
		if(divid!=null&&divid!=""){
			_divid = divid;
		}
		if(projection!=null&&projection!=""){
			_projection = projection;
		}
		if(numpos!=null&&numpos!=""){
			_numpos = numpos;
		}
		//实例化鼠标位置控件（MousePosition）
        this.mousePositionControl = new ol.control.MousePosition({
            //坐标格式
            coordinateFormat: ol.coordinate.createStringXY(_numpos),
            //地图投影坐标系（若未设置则输出为默认投影坐标系下的坐标）
            projection: _projection,
            //坐标信息显示样式类名，默认是'ol-mouse-position'
            className: 'custom-mouse-position',
            //显示鼠标位置信息的目标容器
            target: document.getElementById(_divid),
            //未定义坐标的标记
            undefinedHTML: '&nbsp;'
        });
        this.map.addControl(this.mousePositionControl);
	},
	/**
	 * 地图控件-从地图上移除鼠标位置控件.
	 * 20180823 雷志强
	 */
	removeMousePositionControl:function(){
		if(this.mousePositionControl!=null){
			this.map.removeControl(this.mousePositionControl);
			this.mousePositionControl = null;
		}
	},
	/**
	 * 地图控件-在地图上添加比例尺控件.
	 * 20180823 雷志强
	 * @param {Object} units
	 */
	addScaleLineControl:function(units){
		var _units = "metric";
		if(units!=null&&units!=""){
			_units = units;
		}
		if(this.scaleLineControl!=null){
			return;
		}
		//实例化比例尺控件（ScaleLine）
        this.scaleLineControl = new ol.control.ScaleLine({
            //设置比例尺单位，degrees、imperial、us、nautical、metric（度量单位）
            units: _units 
        });
        this.map.addControl(this.scaleLineControl);
	},
	/**
	 * 地图控件-从地图上移除比例尺控件.
	 * 20180829 雷志强
	 */
	removeScaleLineControl:function(){
		if(this.scaleLineControl!=null){
			this.map.removeControl(this.scaleLineControl);
			this.scaleLineControl = null;
		}
	},
	/**
	 * 地图图层操作-加载MapGIS瓦片地图
	 * 20180726 雷志强
	 * @param {String} layername 图层名称，例如：影像
	 * @param {String} mapname 瓦片地图名称(发布的地图名称)，例如：TILE_CHINA
	 * @param {String} serverIp gis服务ip地址，例如：192.168.10.174
	 * @param {String} serverPort gis服务端口，例如：6163
	 * @param {Object} options 地图参数对象，扩展对象
	 */
	addMapGISTileLayer:function(layername,mapname,serverIp,serverPort,options){
		var self = this;
		var tileLayer = new Zondy.Map.TileLayer(layername, mapname, {
            ip: serverIp,
            port: serverPort
        });
        this.map.addLayer(tileLayer);
//      $.getJSON("http://"+serverIp+":"+serverPort+"/igs/rest/mrms/info/"+mapname, function(mapinfo){
//			console.log(mapinfo);
//			var cx = (mapinfo.xMin + mapinfo.xMax)/2;
//			var cy = (mapinfo.yMin + mapinfo.yMax)/2;
//			console.log(cx+","+cy);
//			self.setCenter([cx,cy],parseInt((mapinfo.startLevel+mapinfo.endLevel)/2,10));
//		});
        this.mapLayers[layername] = tileLayer;
        return tileLayer;
	},
	/**
	 * 地图图层操作-加载MapGIS矢量地图
	 * 20180911 雷志强
	 * @param {String} layername 图层名称，例如：影像
	 * @param {String} mapname 矢量地图名称(发布的地图名称)，例如：VECTOR_CHINA
	 * @param {String} serverIp gis服务ip地址，例如：192.168.10.174
	 * @param {String} serverPort gis服务端口，例如：6163
	 * @param {Object} options 地图参数对象，扩展对象
	 */
	addMapGISDocLayer:function(layername,mapname,serverIp,serverPort,options){
		var docLayer = new Zondy.Map.Doc(layername, mapname, {
            ip: serverIp,
            port: serverPort
        });
        this.map.addLayer(docLayer);
        this.mapLayers[layername] = docLayer;
        return docLayer;
	},
	/**
	 * 地图图层操作-加载MapGIS瓦片图层
	 * 20180911 雷志强
	 * @param {String} layername 图层名称，例如：影像
	 * @param {Array} gdbps 要显示的图层的gdbps地址数组，例如：["gdbp://MapGisLocal/OpenLayerVecterMap/ds/世界地图经纬度/sfcls/世界政区", "gdbp://MapGisLocal/OpenLayerVecterMap/ds/世界地图经纬度/sfcls/世界河流"]
	 * @param {String} serverIp gis服务ip地址，例如：192.168.10.174
	 * @param {String} serverPort gis服务端口，例如：6163
	 * @param {Object} options 地图参数对象，扩展对象
	 */
	addMapGISVectorLayer:function(layername,gdbps,serverIp,serverPort,options){
        var vectorLayer = new Zondy.Map.Layer(name, gdbps, {
            ip: serverIp,
            port: serverPort
        });
        this.map.addLayer(vectorLayer);
        this.mapLayers[layername] = vectorLayer;
        return vectorLayer;
	},
	/**
	 * 地图图层操作-加载WMS地图以矢量方式显示
	 * 20180911 雷志强
	 * @param {String} layername 图层名称，例如：影像
	 * @param {String} url 基于地图文档的WMS访问基地址，例如：http://develop.smaryun.com:6163/igs/rest/ogc/doc/WorldJWVector/WMSServer
	 * @param {String} layers 地图图层字符串，格式为：地图名称:图层名称1,图层名称2，例如:WorldJWVector:世界政区,国界线.wl,中国国界线,中国省界_不含国界,世界河流,洲洋注记_1,中国注记
	 */
	addImageWMS:function(layername,url,layers){
		var wmsLayer = new ol.layer.Image({
            title: layername,
            source: new ol.source.ImageWMS({
                //WMS服务地址
                url: url,
                //图层等参数
                params: {'LAYERS':layers,'TILED':true},
                //服务类型
                serverType: 'geoserver'
            })
        });
        this.map.addLayer(wmsLayer);
        this.mapLayers[layername] = wmsLayer;
        return wmsLayer;
	},
	/**
	 * 地图图层操作-加载WMS地图以瓦片方式显示
	 * 20180911 雷志强
	 * @param {String} layername 图层名称，例如：影像
	 * @param {String} url 基于地图文档的WMS访问基地址，例如：http://develop.smaryun.com:6163/igs/rest/ogc/doc/WorldJWVector/WMSServer
	 * @param {String} layers 地图图层字符串，格式为：地图名称:图层名称1,图层名称2，例如:WorldJWVector:世界政区,国界线.wl,中国国界线,中国省界_不含国界,世界河流,洲洋注记_1,中国注记
	 */
	addTileWMS:function(layername,url,layers){
		var wmsLayer = new ol.layer.Tile({
            title: layername,
            source: new ol.source.TileWMS({
                //WMS服务地址
                url: url,
                //图层等参数
                params: {'LAYERS':layers,'TILED':true},
                //服务类型
                serverType: 'geoserver'
            })
        });
        this.map.addLayer(wmsLayer);
        this.mapLayers[layername] = wmsLayer;
        return wmsLayer;
	},
	addWFSLayer:function(){
		
	},
	/**
	 * 地图图层操作-加载标准WMTS地图
	 * 20180912 雷志强
	 * @param {String} layername 图层名称，例如：影像
	 * @param {String} url WMTS服务基地址，例如：http://develop.smaryun.com:6163/igs/rest/ogc/WMTSServer
	 * @param {String} mapname WMTS服务图层名称，例如：WhMapTileWMTS
	 * @param {String} projection 数据的投影坐标系，例如：EPSG:4326
	 */
	addWMTSLayer:function(layername,url,mapname,projection){
		var projectionExtent = ol.proj.get(projection).getExtent();
		var size = ol.extent.getWidth(projectionExtent) / 256;
	    var resolutions = new Array(21);
	    var matrixIds = new Array(21);
	    for (var i = 0; i < 21; i++) {
	        resolutions[i] = size / Math.pow(2, i);
	        matrixIds[i] = i;
	    }
	    var layer = new ol.layer.Tile({
	        source: new ol.source.WMTS({
	        	//WMTS服务基地址
	            url: url,
	            //WMTS服务图层
                layer: mapname,
	            tileGrid: new ol.tilegrid.WMTS({
	            	//原点（左上角
	                origin: ol.extent.getTopLeft(projectionExtent),
	                //分辨率数组
	                resolutions: resolutions,
	                //矩阵标识列表，与地图级数保持一致
	                matrixIds: matrixIds
	            }),
	            //瓦片图片格式
	            format: 'image/png',
	            //数据的投影坐标系
	            projection: projection
	        })
	    });
	    this.map.addLayer(layer);
        this.mapLayers[layername] = layer;
	    return layer;
	},
	/**
	 * 地图图层操作-加载PGIS地图
	 * 20180912 雷志强
	 * @param {String} layername 图层名称
	 * @param {String} url PGIS地图服务地址
	 * @param {String} mapname 地图名称
	 * @param {String} projection 投影坐标系
	 */
	addPGISLayer:function(layername,url,mapname,projection){
		var projectionExtent = ol.proj.get(projection).getExtent();
		var size = ol.extent.getWidth(projectionExtent) / 256;
	    var resolutions = new Array(21);
	    var matrixIds = new Array(21);
	    for (var i = 0; i < 21; i++) {
	        resolutions[i] = size / Math.pow(2, i);
	        matrixIds[i] = i;
	    }
	    var layer = new ol.layer.Tile({
	        source: new ol.source.WMTS({
	        	name:mapname,
	            url: url,
	            tileGrid: new ol.tilegrid.WMTS({
	                origin: ol.extent.getTopLeft(projectionExtent),
	                resolutions: resolutions,
	                matrixIds: matrixIds
	            }),
	            format: 'image/png',
	            projection: projection,
	            layer:mapname
	        })
	    });
	    this.map.addLayer(layer);
        this.mapLayers[layername] = layer;
	    return layer;
	},
//	function zeroPad(num, len, radix) {
//			var str = num.toString(radix||10);
//			while (str.length < len) {
//				str = "0" + str;
//			}
//			return str;
//		}
//		// ol.source.XYZ添加瓦片地图的层
//		var tileLayer = new ol.layer.Tile({
//			source: new ol.source.XYZ({
//			//projection: 'EPSG:4326',
//			tileSize:256,
//				tileUrlFunction: function (tileCoord) {
//			   //     alert(tileCoord[0] + " X= " + tileCoord[1] + " Y= " + tileCoord[2]);
//				   var x = 'C' + zeroPad(tileCoord[1], 8, 16);
//				   var y = 'R' + zeroPad(-tileCoord[2] -1, 8, 16);				
//				   var z = 'L' + zeroPad(tileCoord[0], 2, 10);
//				   return  '../hagdmap/_alllayers/' + z + '/' + y + '/' + x + '.png';
//				  // return  'download/googlemaps/roadmap/' + tileCoord[0] + '/' + (-tileCoord[2]-1) + '/' + tileCoord[1] + '.png';
//				},
//				projection: 'EPSG:3857',
//				wrapX:false
//			})
//		});
	/**
	 * 地图图层操作-添加矢量要素图层
	 * @param {String} layername 图层名称
	 */
	addVectorLayer:function(layername,source){
		if(source == null){
			//实例化一个矢量图层Vector作为绘制层
			source = this.createVectorSource();
		}
        //创建一个图层
        var vector = new ol.layer.Vector({
            source: source
        });
        this.map.addLayer(vector);
        this.mapLayers[layername] = vector;
        return vector;
	},
	/**
	 * 地图图层操作-添加热力图图层
	 * 20180914 雷志强
	 * @param {String} layername 图层名称
	 * @param {Array} features 数据源要素对象
	 * @param {String} valattr 需要生成热力图的属性，例如:personCount
	 * @param {Number} radius 热点半径，例如：20
	 * @param {Number} blursize 模糊尺寸，例如：20
	 */
	addHeatmapLayer:function(layername,features,valattr,radius,blursize){
		//创建矢量数据源
		var source = new ol.source.Vector({
            features: features
        });
        var featureRect = this.getFeaturesRect(features);
        //创建热力图图层
		var heatmapLayer = new ol.layer.Heatmap({
            source: source,
            //热点半径
            radius: parseInt(radius, 10),
            //模糊尺寸
            blur: parseInt(blursize, 10)
        });
        //为矢量数据源添加addfeature事件监听
        heatmapLayer.getSource().on('addfeature', function (event) {
            //获取生成热力图的对应的属性
            var htvalue = event.feature.get(valattr);
            var ht_weight = parseFloat(htvalue);
            //设置要素的weight属性
            event.feature.set('weight', ht_weight - 5);
        });
		this.map.addLayer(heatmapLayer);
        this.mapLayers[layername] = heatmapLayer;
        this.viewInRect(featureRect);
		return heatmapLayer;
	},
	/**
	 * 地图图层操作-根据图层名称获取图层对象
	 * 20180912 雷志强
	 * @param {Object} layername
	 */
	getLayerByName:function(layername){
		var layer = null;
		if(layername in this.mapLayers){
			layer = this.mapLayers[layername];
		}
		return layer;
	},
	/**
	 * 地图图层操作-移除指定的图层
	 * @param {Object} layer 地图图层对象
	 */
	removeLayer:function(layer){
		if(layer!=null){
			this.map.removeLayer(layer);
		}
	},
	/**
	 * 地图图层操作-移除指定名称的图层
	 * 20180911 雷志强
	 * @param {Object} layername 图层名称
	 */
	removeLayerByName:function(layername){
		if(layername in this.mapLayers){
			this.removeLayer(this.mapLayers[layername]);
			delete this.mapLayers[layername];
		}
	},
	/**
	 * 地图基本操作--地图缩小一级
	 */
	zoomOut:function(){
		if(this.map!=null&&this.map.getView()!=null){
			this.setZoom(this.getZoom() - 1);
		}
	},
	/**
	 * 地图基本操作--地图放大一级
	 */
	zoomIn:function(){
		if(this.map!=null&&this.map.getView()!=null){
			this.setZoom(this.getZoom() + 1);
		}
	},
	/**
	 * 地图基本操作--地图定位到指定坐标点
	 * @param {Object} coordinate 坐标，格式为：[x,y];例如：[113.42,30.145]
	 */
	panTo:function(coordinate){
		if(this.map!=null&&this.map.getView()!=null)
		this.map.getView().setCenter(coordinate);
	},
	/**
	 * 地图基本操作--设置地图中心点并自动定位到中心点
	 * @param {Object} coordinate 中心点坐标，格式为：[x,y];例如：[113.42,30.145]
	 * @param {Object} zoom 地图级别，例如：4
	 */
	setCenter:function(coordinate,zoom){
		if(this.map!=null&&this.map.getView()!=null){
			this.map.getView().setCenter(coordinate);
			this.setZoom(zoom);
			console.log("zoom="+zoom);
		}
	},
	/**
	 * 地图基本操作--根据矩形范围进行定位显示地图
	 * 20181009 雷志强:修改完善了根据矩形范围显示中放大级数计算错误的问题
	 * @param {Array} extent 矩形范围，格式[xmin,ymin,xmax,ymax]
	 */
	viewInRect:function(extent){
		var resolution = this.getResolution();
        var zoom = this.getZoom();
        var size = this.getViewSize();
        var dx = extent[2] - extent[0];
    	var dy = extent[3] - extent[1];
    	//定位中心点
    	var cx = (extent[0] + extent[2])/2;
    	var cy = (extent[1] + extent[3])/2;
    	//最佳显示X方向分辨率
    	var rx = dx / size[0];
    	//最佳显示Y方向分辨率
    	var ry = dy / size[1];
    	var xlog2val = resolution/rx;
    	var ylog2val = resolution/ry;
    	//以最小的值来计算放大级数，以2为底求对数计算放大级数
    	var log2val = Math.min(resolution/rx,resolution/ry);
    	var zoomCount = Math.log2(log2val);
    	var zoomIndex = Math.floor(zoomCount);
    	var _zoom = zoom + zoomIndex;
    	this.setCenter([cx,cy],_zoom);
	},
	/**
	 * 地图基本操作--拉框交互放大地图.
	 */
	zoomInRect:function(){
		var geomtype = "LineString";
		var maxPoints = 2;
		this.drawinfo.layer = this.addVectorLayer("交互操作");
		var source = this.drawinfo.layer.getSource();
		var draw = new ol.interaction.Draw({
            source: source,//测量绘制层数据源
            type: geomtype,  //几何图形类型
            //freehand: true,
            //几何信息变更时调用函数
            geometryFunction: function(coordinates, geometry){
            	if (!geometry) {
		            //多边形
		            geometry = new ol.geom.Polygon(null);
		        }
		        var start = coordinates[0];
		        var end = coordinates[1];
		        geometry.setCoordinates([
		            [start, [start[0], end[1]], end, [end[0], start[1]], start]
		        ]);
		        return geometry;
            },
            //最大点数
            maxPoints: maxPoints
        });
        this.map.removeInteraction(draw);
        this.map.addInteraction(draw);
        this.drawinfo.draw = draw;
        var _this = this;
        var listener;
        //绑定交互绘制工具结束绘制的事件
        draw.on('drawend',
            function (evt) {
                var polygon = evt.feature.getGeometry();
                this.map.removeInteraction(this.drawinfo.draw);
                this.map.removeLayer(this.drawinfo.layer);
                this.drawinfo.draw = null;
                _this.viewInRect(polygon.getExtent());
            }, this);
	},
	/**
	 * 地图基本操作--获取地图视图对象
	 * 20180911  雷志强
	 */
	getView:function(){
		var view = null;
		if(this.map!=null&&this.map.getView()!=null){
			view = this.map.getView();
		}
		return view;
	},
	/**
	 * 地图基本操作--获取当前显示级别
	 * 20180911  雷志强
	 * @return {Number} 地图当前显示级别，例如：4
	 */
	getZoom:function(){
		var zoom = 3;
		if(this.map!=null&&this.map.getView()!=null){
			zoom = this.map.getView().getZoom();
		}
    	return zoom;
	},
	/**
	 * 地图基本操作--设置地图显示级别
	 * 20180911  雷志强
	 * @param {Number} zoom 地图级别(整数)，例如：4
	 */
	setZoom:function(zoom){
		if(this.map!=null&&this.map.getView()!=null)
		this.map.getView().setZoom(zoom);
	},
	/**
	 * 地图基本操作--获取当前地图显示分辨率
	 * 20180911  雷志强
	 * @return {Number} 地图显示分辨率，例如：0.152356
	 */
	getResolution:function(){
		var curResolution = 0.005;
		if(this.map!=null&&this.map.getView()!=null){
			curResolution = this.map.getView().getResolution();
		}
		return curResolution;
	},
	/**
	 * 地图基本操作--获取当前地图显示范围
	 * 20180911  雷志强
	 * @return {Array} 地图显示范围，格式[xmin,ymin,xmax,ymax]，例如：[114.515,30.314,115.156,31.2145]
	 */
	getViewBound:function(){
		var bound = [-180,-90,180,90];
		if(this.map!=null&&this.map.getView()!=null){
			bound = this.map.getView().calculateExtent(this.map.getSize());
		}
		return bound;
	},
	/**
	 * 地图基本操作--获取当前地图视窗范围
	 * 20180911  雷志强
	 * @return {Array} 地图视窗范围，格式[width,height]，例如：[800,600]
	 */
	getViewSize:function(){
		var viewSize = [800,600];
		if(this.map!=null){
			viewSize = this.map.getSize();
		}
		return viewSize;
	},
	getMapImage:function(){
		
	},
	/**
	 * 地图基本操作--设置图层显示隐藏
	 * 20180912 雷志强
	 * @param {Object} layer 图层对象
	 * @param {Boolean} visible true-显示|false-隐藏
	 */
	setLayerVisible:function(layer,visible){
		if(layer!=null){
			try{
				layer.setVisible(visible);
			}catch(e){
				console.log(e);
			}
		}
	},
	/**
	 * 地图基本操作--设置图层透明度
	 * 20180912 雷志强
	 * @param {Object} layer 图层对象
	 * @param {Number} opacity 透明度值，范围0~1，例如:0.5
	 */
	setLayerOpacity:function(layer,opacity){
		if(layer!=null){
			try{
				layer.setOpacity(opacity);
			}catch(e){
				console.log(e);
			}
		}
	},
	/**
	 * 地图基本操作--设置图层顶底显示
	 * 20180912 雷志强
	 * @param {Object} layer 图层对象
	 */
	showLayerTop:function(layer){
		if(layer==null){return;}
		if(this.map!=null){
			var layers=this.map.getLayerGroup().getLayers().getArray();
		    for(var i=0;i<layers.length;i++){
		        if(layers[i].getVisible()==true && layer[i]!=layer){
		        	if(layers[i].getZIndex()>0){
		        		layers[i].setZIndex(layers[i].getZIndex()-1);
		        	}
		        }
		    }
		    layer.setZIndex(layers.length);
		}
	},
	/**
	 * 设置图层显示层级.
	 * 20181009 雷志强
	 * @param {ol.Layer} layer 图层对象
	 * @param {Number} index 图层层级数值，例如：9
	 */
	setLayerZIndex:function(layer,index){
		if(layer!=null){
			layer.setZIndex(index);
		}
	},
	/**
	 * 创建一个矢量图层数据源
	 * @param {Array} 要素数组对象
	 * @param {Object} 数据源参数，扩展参数
	 */
	createVectorSource:function(features,options){
		var feature_data = features;
		if(typeof(features)=="undefined"){
			feature_data = [];
		}
		//实例化一个矢量图层Vector作为绘制层
        var source = new ol.source.Vector({
            features: feature_data
        });
        return source;
	},
	/**
	 * 创建矢量点要素对象
	 * @param {Array} coordinate 坐标点，格式为：[x,y];例如：[113.42,30.145]
	 * @param {Object} style 矢量要素样式，可以为null，则使用默认样式，如要设置样式，例如：new ol.style.Style
	 */
	createPointFeature:function(coordinate,style){
		var point = new ol.Feature({
            geometry: new ol.geom.Point(coordinate)
        });
        if(style!=null){
        	point.setStyle(style);
        }
        return point;
	},
	/**
	 * 创建矢量线要素对象
	 * @param {Array} points 线坐标点数组,格式为：[[x,y],[x,y],[x,y]];例如：[[113.42,30.14],[113.65,30.57],[113.98,31.41]]
	 * @param {Object} style 矢量要素样式，可以为null，则使用默认样式，如要设置样式，例如：new ol.style.Style
	 */
	createLineFeature:function(points,style){
		//创建一个线
        var line = new ol.Feature({
            geometry: new ol.geom.LineString(points)
        });
        if(style!=null){
        	line.setStyle(style);
        }
        return line;
	},
	/**
	 * 创建矢量圆要素对象
	 * @param {Array} coordinate 中心点，格式为：[x,y];例如：[113.42,30.145]
	 * @param {Number} radius 圆半径(单位：坐标差值，即x2-x1)，例如：0.5672
	 * @param {Object} style 矢量要素样式，可以为null，则使用默认样式，如要设置样式，例如：new ol.style.Style
	 */
	createCircleFeature:function(coordinate,radius,style){
		//创建一个圆
        var circle = new ol.Feature({
            geometry: new ol.geom.Circle(coordinate, radius)
        });
        if(style!=null){
        	circle.setStyle(style);
        }
        return circle;
	},
	/**
	 * 创建矢量多边形要素对象
	 * @param {Array} points points 多边形边界坐标点数组,格式为：[[x,y],[x,y],[x,y]];例如：[[113.42,30.14],[113.65,30.57],[113.98,31.41]]
	 * @param {Object} style 矢量要素样式，可以为null，则使用默认样式，如要设置样式，例如：new ol.style.Style
	 */
	createPolygonFeature:function(points,style){
		//创建一个多变形
        var polygon = new ol.Feature({
            geometry: new ol.geom.Polygon([points])
        });
        if(style!=null){
        	polygon.setStyle(style);
        }
        return polygon;
	},
	/**
	 * 将矢量要素添加到矢量图层上.
	 * @param {Object} layer 矢量图层对象
	 * @param {Object} feature 矢量要素对象
	 */
	addVectorFeature:function(layer,feature){
		if(layer!=null){
			if(feature!=null && typeof(feature)!="undefined"){
				layer.getSource().addFeature(feature);
			}
		}
	},
	addMarkers:function(layer,points,option){
		
	},
	/**
	 * 获取矢量要素图层的所有要素.
	 * 20181009 雷志强
	 * @param {Object} layer 矢量图层对象
	 */
	getVectorFeatures:function(layer){
		var features = [];
		if(layer!=null){
			var source = layer.getSource();
			if(source!=null){
				features = source.getFeatures();
			}
		}
		return features;
	},
	/**
	 * 根据要素类型移除要素.
	 * 20181009 雷志强
	 * @param {Object} layer 矢量图层对象
	 * @param {String} type 要素类型，需要给要素添加type属性，设置要素类型，通用这个type进行要素删除
	 */
	removeFeatureByType:function(layer,type){
		var features = this.getVectorFeatures(layer);
		console.log("获取矢量要素["+features.length+"]个");
		if(features.length>0){
			if(type!=null && typeof(type)!="undefined"){
				var feature = null;
				var deleteCount = 0;
				for(var i=0;i<features.length;i++){
					feature = features[i];
					if(feature.type==type){
						layer.getSource().removeFeature(feature);
						deleteCount++;
					}
				}
				console.log("清除类型为["+type+"]的要素["+deleteCount+"]个");
			}
		}
	},
	/**
	 * 删除指定ID的要素.
	 * 20181009 雷志强
	 * @param {Object} layer 矢量图层对象
	 * @param {String} ids 要素ID集合字符串,多个id用,隔开；例如：point1,point2,point3
	 */
	removeFeatureById:function(layer,ids){
		var features = this.getVectorFeatures(layer);
		console.log("获取矢量要素["+features.length+"]个");
		if(ids!=null && typeof(ids)!="undefined"){
			var idArr = ids.split(",");
			var feature = null;
			var deleteCount = 0;
			var source = layer.getSource();
			for(var i=0;i<idArr.length;i++){
				feature = source.getFeatureById(idArr[i]);
				if(feature!=null){
					layer.getSource().removeFeature(feature);
					deleteCount++;
				}
			}
			console.log("清除符合条件的要素["+deleteCount+"]个");
		}
		/**
		var features = this.getVectorFeatures(layer);
		console.log("获取矢量要素["+features.length+"]个");
		if(features.length>0){
			if(ids!=null && typeof(ids)!="undefined"){
				var idArr = ids.split(",");
				var feature = null;
				var deleteCount = 0;
				for(var i=0;i<features.length;i++){
					feature = features[i];
					if(idArr.contains(feature.id)){
						layer.getSource().removeFeature(feature);
						deleteCount++;
					}
				}
				console.log("清除符合条件的要素["+deleteCount+"]个");
			}
		}
		*/
	},
	/**
	 * 移除矢量图层所有要素.
	 * 20181009 雷志强
	 * @param {Object} layer 矢量图层对象
	 */
	removeAllFeature:function(layer){
		if(layer!=null){
			var source = layer.getSource();
			if(source!=null){
				source.clear(true);
			}
		}
	},
	/**
	 * 获取要素的外包矩形范围(用于定位显示).
	 * @param {Array} features 要素对象数组集合.
	 */
	getFeaturesRect:function(features){
		var featureRect = [0,0,0,0];
		if(features!=null && Array.isArray(features)){
			var count = features.length;
			var feature = null;
			var featureType = "Point";
	        var popupCoordinate = null;
	        var coordinates = [];
	        var pointArray = [];
			for(var i=0;i<count;i++){
				feature = features[i];
				featureType = feature.values_.geometry.getType();
				if(featureType=="Point"){
					coordinates = feature.getGeometry().getCoordinates();
					console.log(coordinates);
					pointArray.push({x:coordinates[0],y:coordinates[1]});
				}
			}
			var rect = this.getPointsRect(pointArray);
			console.log(rect);
			featureRect=[rect.xmin,rect.ymin,rect.xmax,rect.ymax];
		}
		console.log(featureRect);
		return featureRect;
	},
	/**
	 * 创建矢量要素样式.
	 * @author 雷志强 20180914
	 * @param {Object} option 参数对象，包括属性:fillColor-填充色|strokeColor-线颜色|strokeWidth-线宽|imageRadius-圆半径|imageFillColor-圆填充色
	 */
	createFeatureStyle:function(option){
		var opt = {
			fillColor:"rgba(255, 255, 255, 0.7)",
			strokeColor:"rgba(0, 0, 255, 0.8)",
			strokeWidth:2,
			imageRadius:15,
			imageFillColor:"rgba(255, 255, 0, 0.8)"
		};
		$.extend(true, opt, option);
		var fstyle = new ol.style.Style({
            //填充色
            fill: new ol.style.Fill({
                color: opt.fillColor
            }),
            //边线颜色
            stroke: new ol.style.Stroke({
                color: opt.strokeColor,
                width: opt.strokeWidth
            }),
            //形状
            image: new ol.style.Circle({
                radius: opt.imageRadius,
                stroke: new ol.style.Stroke({
	                color: opt.strokeColor,
	                width: opt.strokeWidth
	            }),
                fill: new ol.style.Fill({
                    color: opt.imageFillColor
                })
            })
        });
        return fstyle;
	},
	/**
	 * 创建图文标注显示样式
	 * 雷志强20180917
	 * @param {Object} iconurl 标注图片地址
	 * @param {Object} text 要显示的文本
	 * @param {Object} option 样式对象
	 */
	createIconStyle:function(iconurl,text,option){
		var opt = {
			anchorX:0.5,
			anchorY:0,
			opacity:0.8,//透明度
			oleft:0,
			otop:0,
			textBaseline:"middle",
			fontsize:14,
			fontcolor:'yellow',
			strokeWidth:2,
			strokeColor:"#ffcc33",
			offsetY:20
		};
		$.extend(true, opt, option);
		return new ol.style.Style({
            image: new ol.style.Icon({
                anchor: [opt.anchorX, opt.anchorY],
                anchorOrigin: 'top-right',
                anchorXUnits: 'fraction',
                anchorYUnits: 'pixels',
                offsetOrigin: 'top-right',
                //offset:[opt.oleft,opt.otop],
                //图标缩放比例
                //scale:0.5,
                //透明度
                opacity: opt.opacity,
                //图标的url
                src: iconurl
            }),
            text: new ol.style.Text({
                //位置
                textAlign: 'center',
                //基准线
                textBaseline: 'top',
                //文字样式
                font: 'normal '+opt.fontsize+'px 微软雅黑',
                //文本内容
                text: text,
                offsetY:option.offsetY,
                //文本填充样式（即文字颜色）
                fill: new ol.style.Fill({ color: opt.fontcolor }),
                stroke: new ol.style.Stroke({color:opt.strokeColor, width: opt.strokeWidth })
            })
        });
	},
	/**
	 * 创建文本标注样式对象
	 * 雷志强20180917
	 * @param {String} text 要显示的文本内容
	 * @param {Object} option 样式对象
	 */
	createLabelStyle:function(text,option){
		var opt = {
			textAlign:"center",
			textBaseline:"middle",
			font:'normal 14px 微软雅黑',
			fillColor:'#aa3300',
			strokeWidth:2,
			strokeColor:"#ffcc33"
		};
		$.extend(true, opt, option);
		return new ol.style.Style({
            text: new ol.style.Text({
                //位置
                textAlign: opt.textAlign,
                //基准线
                textBaseline: opt.textBaseline,
                //文字样式
                font:opt.font,
                //文本内
                text: text,
                //文本填充样式（即文字颜色）
                fill: new ol.style.Fill({color:opt.fillColor}),
                stroke: new ol.style.Stroke({color:opt.strokeColor,width:opt.strokeWidth})
            })
        });
	},
	/**
	 * 初始化标注点气泡显示事件
	 * 雷志强20180917
	 */
	initShowPopupEvent:function(){
		var self = this;
		self.map.on('click', function (evt) {
			console.log(evt);
			var clickPoint = evt.coordinate;
            //判断当前单击处是否有要素，捕获到要素时弹出popup
            var feature = self.map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) { return feature; });
            if (feature) {
            	feature.clickPoint = clickPoint;
            	console.log(feature);
            	try{
            		//是否显示气泡
            		var showpopup = feature.showpopup;
            		//标注点气泡dom对象ID
            		var popupId = feature.popupid;
            		//标注点气泡中需要显示的html内容
            		var popuphtml = feature.popuphtml;
            		if(popuphtml==null){
            			popuphtml = "<label style='color:red;'>提示说明：要素对象缺少popuphtml属性，无法显示气泡详细信息内容！</label>";
            		}
            		if(showpopup){
            			var popupElement = document.getElementById(popupId);
            			if(popupElement!=null){
            				popupElement.innerHTML = popuphtml;
            				self.showOnePopup(popupElement,200,feature);
            			}
            		}
            	}catch(e){
            		console.log(e);
            	}
            }
        });
       	//为map添加鼠标移动事件监听，当指向标注时改变鼠标光标状态
        self.map.on('pointermove', function (e) {
            var pixel = self.map.getEventPixel(e.originalEvent);
            var hit = self.map.hasFeatureAtPixel(pixel);
            self.map.getTargetElement().style.cursor = hit ? 'pointer' : '';
        });
	},
	/**
	 * 显示标注气泡信息提示框
	 * 雷志强20180917
	 * @param {Object} popupElement 气泡dom对象，即document.getElementById('popup')
	 * @param {Number} popupWidth 气泡显示的宽度(数值)，例如：200
	 * @param {ol.Feature} feature 需要显示气泡信息框的要素对象
	 */
	showOnePopup:function(popupElement,popupWidth,feature){
		if(popupElement!=null){
			try{
				popupElement.style.display = "block";
			}catch(e){}
		}
        if(this.onePopup == null){
        	var popup = new ol.Overlay({
	            //要转换成overlay的HTML元素
	            element: popupElement,
	            //当前窗口可见
	            autoPan: true,
	            //Popup放置的位置
	            positioning: 'bottom-center',
	            //是否应该停止事件传播到地图窗口
	            stopEvent: false,
	            autoPanAnimation: {
	                //当Popup超出地图边界时，为了Popup全部可见，地图移动的速度
	                duration: 250
	            }
	        });
        	this.onePopup = popup;
        	this.map.addOverlay(popup);
        }
        popupElement.style.width = popupWidth+"px";
        var padding = this.getDomStyle(popupElement,"padding");
        popupElement.style.left = -1*((popupWidth/2) + parseInt(padding)) +"px";
        this.closeOnePopup();
        //获取要素类型
        var featureType = feature.values_.geometry.getType();
        console.log(featureType);
        var popupCoordinate = null;
        var coordinates = feature.getGeometry().getCoordinates();
        console.log(coordinates);
        if(featureType=="Point"){
        	popupCoordinate = coordinates;
        }else{
        	popupCoordinate = feature.clickPoint;
        }
        if (this.onePopup.getPosition() == undefined) {
            //设置popup的位置
            this.onePopup.setPosition(popupCoordinate);
        }
	},
	/**
	 * 关闭标注气泡
	 * 雷志强20180917
	 */
	closeOnePopup:function(){
		this.onePopup.setPosition(undefined);
	},
	startDrawFeature:function(layer,geometryType,geometryFunction){
		this.stopDrawFeature();
		if(layer==null){
			alert("矢量绘制图层对象不能为空！");
			return;
		}
		var source = layer.getSource();
		this.drawLayer = layer;
		var drawInteractionOption = {
			//绘制层数据源
            source: source,
            /** @type {ol.geom.GeometryType}几何图形类型 */
            type: geometryType
		};
		//实例化交互绘制类对象并添加到地图容器中
        this.featureDraw = new ol.interaction.Draw(drawInteractionOption);
        this.map.addInteraction(this.featureDraw);
		/**
		console.log(geometryType);
		this.stopDrawFeature();
		//var source = this.createVectorSource();
		var source = new ol.source.Vector({ wrapX: false });
		this.addVectorLayer("交互绘制图层",source);
		var geometryType = "";
		var maxPoints = 4;
		//实例化交互绘制类对象并添加到地图容器中
        this.featureDraw = new ol.interaction.Draw({
            //绘制层数据源
            source: source,
            / * * @type {ol.geom.GeometryType}几何图形类型 * /
            type: geometryType,
            //几何信息变更时调用函数
            geometryFunction: geometryFunction,
            //最大点数
            maxPoints: maxPoints
        });
        this.map.addInteraction(this.featureDraw);
        */
	},
	stopDrawFeature:function(clearFeatures){
		this.map.removeInteraction(this.featureDraw);
		if(clearFeatures!=null && clearFeatures){
			this.map.removeLayer(this.drawLayer);
			this.drawLayer = null;
		}
	},
	/**
	 * 创建测量矢量绘制图层.
	 */
	createMeasureLayer:function(){
		//加载测量的绘制矢量层
        var source = new ol.source.Vector(); //图层数据源
        var vector = new ol.layer.Vector({
            source: source,
            style: new ol.style.Style({ //图层样式
                fill: new ol.style.Fill({
                    color: 'rgba(255, 255, 255, 0.2)' //填充颜色
                }),
                stroke: new ol.style.Stroke({
                    color: '#ffcc33',  //边框颜色
                    width: 2   // 边框宽度
                }),
                image: new ol.style.Circle({
                    radius: 7,
                    fill: new ol.style.Fill({
                        color: '#ffcc33'
                    })
                })
            })
        });
        this.map.addLayer(vector);
        this.measure.layer = vector;
	},
	createHelpTooltip:function(){
		if (this.measure.helpTooltipElement) {
            this.measure.helpTooltipElement.parentNode.removeChild(this.measure.helpTooltipElement);
        }
        this.measure.helpTooltipElement = document.createElement('div');
        this.measure.helpTooltipElement.className = 'tooltip hidden';
        this.measure.helpTooltip = new ol.Overlay({
            element: this.measure.helpTooltipElement,
            offset: [15, 0],
            positioning: 'center-left'
        });
        this.map.addOverlay(this.measure.helpTooltip);
	},
	createMeasureTooltip:function(){
		if (this.measure.measureTooltipElement) {
            this.measure.measureTooltipElement.parentNode.removeChild(this.measure.measureTooltipElement);
        }
        this.measure.measureTooltipElement = document.createElement('div');
        this.measure.measureTooltipElement.className = 'tooltip tooltip-measure';
        this.measure.measureTooltip = new ol.Overlay({
            element: this.measure.measureTooltipElement,
            offset: [0, -15],
            positioning: 'bottom-center'
        });
        this.map.addOverlay(this.measure.measureTooltip);
	},
	/**
	 * 测量工具-测量距离
	 */
	measureLength:function(){
		this.startMeasure("length");
	},
	/**
	 * 测量工具-测量面积
	 */
	measureArea:function(){
		this.startMeasure("area");
	},
	/**
	 * 测量工具.
	 * @param {Object} type 测量类型：length-测量距离|area-测量面积
	 */
	startMeasure:function(type){
		var _this = this;
		if(this.measure.draw!=null){
			this.map.removeInteraction(this.measure.draw);
			this.measure.draw = null;
		}
		var sourceType = "LineString";
		if(type=="length"){
			sourceType = "LineString";
		}else{
			sourceType = "Polygon";
		}
		var _useGeodesic = true;
		this.measure.useGeodesic = _useGeodesic;
		if(this.measure.layer==null){
			this.createMeasureLayer();
		}
		/**
         * 当前绘制的要素（Currently drawn feature.）
         * @type {ol.Feature}
         */
        this.measure.sketch = null;
        /**
         * 帮助提示框对象（The help tooltip element.）
         * @type {Element}
         */
        this.measure.helpTooltipElement = null;
        /**
         *帮助提示框显示的信息（Overlay to show the help messages.）
         * @type {ol.Overlay}
         */
        this.measure.helpTooltip = null;
        /**
         * 测量工具提示框对象（The measure tooltip element. ）
         * @type {Element}
         */
        this.measure.measureTooltipElement = null;
        /**
         *测量工具中显示的测量值（Overlay to show the measurement.）
         * @type {ol.Overlay}
         */
        this.measure.measureTooltip = null;
        /**
         *  当用户正在绘制多边形时的提示信息文本
         * @type {string}
         */
        this.measure.continuePolygonMsg = '点击地图绘制多边形进行测量';
        /**
         * 当用户正在绘制线时的提示信息文本
         * @type {string}
         */
        this.measure.continueLineMsg = '点击地图绘制线进行测量';

        /**
         * 鼠标移动事件处理函数
         * @param {ol.MapBrowserEvent} evt
         */
        this.measure.pointerMoveHandler = function (evt) {
            if (evt.dragging) {
                return;
            }
            /** @type {string} */
            var helpMsg = '点击地图进行测量，双击结束';//当前默认提示信息
            //判断绘制几何类型设置相应的帮助提示信息
            if (_this.measure.sketch) {
                var geom = (sketch.getGeometry());
                if (geom instanceof ol.geom.Polygon) {
                    helpMsg = continuePolygonMsg; //绘制多边形时提示相应内容
                } else if (geom instanceof ol.geom.LineString) {
                    helpMsg = continueLineMsg; //绘制线时提示相应内容
                }
            }
            _this.measure.helpTooltipElement.innerHTML = helpMsg; //将提示信息设置到对话框中显示
            _this.measure.helpTooltip.setPosition(evt.coordinate);//设置帮助提示框的位置
            $(_this.measure.helpTooltipElement).removeClass('hidden');//移除帮助提示框的隐藏样式进行显示
        };
        this.map.un('pointermove', this.measure.pointerMoveHandler,this);
        this.map.on('pointermove', this.measure.pointerMoveHandler); //地图容器绑定鼠标移动事件，动态显示帮助提示框内容
        //地图绑定鼠标移出事件，鼠标移出时为帮助提示框设置隐藏样式
        $(this.map.getViewport()).on('mouseout', function () {
            $(_this.measure.helpTooltipElement).addClass('hidden');
        });
        var source = this.measure.layer.getSource();
        var draw; // global so we can remove it later
        draw = new ol.interaction.Draw({
            source: source,//测量绘制层数据源
            type: sourceType,  //几何图形类型
            style: new ol.style.Style({//绘制几何图形的样式
                fill: new ol.style.Fill({
                    color: 'rgba(255, 255, 255, 0.2)'
                }),
                stroke: new ol.style.Stroke({
                    color: 'rgba(0, 0, 0, 0.5)',
                    lineDash: [10, 10],
                    width: 2
                }),
                image: new ol.style.Circle({
                    radius: 5,
                    stroke: new ol.style.Stroke({
                        color: 'rgba(0, 0, 0, 0.7)'
                    }),
                    fill: new ol.style.Fill({
                        color: 'rgba(255, 255, 255, 0.2)'
                    })
                })
            })
        });
        this.map.addInteraction(draw);
		this.measure.draw = draw;
        this.createMeasureTooltip(); //创建测量工具提示框
        this.createHelpTooltip(); //创建帮助提示框

        var listener;
        //绑定交互绘制工具开始绘制的事件
        draw.on('drawstart',
          function (evt) {
              // set sketch
              sketch = evt.feature; //绘制的要素

              /** @type {ol.Coordinate|undefined} */
              var tooltipCoord = evt.coordinate;// 绘制的坐标
              //绑定change事件，根据绘制几何类型得到测量长度值或面积值，并将其设置到测量工具提示框中显示
              listener = sketch.getGeometry().on('change', function (evt) {
                  var geom = evt.target;//绘制几何要素
                  var output;
                  if (geom instanceof ol.geom.Polygon) {
                      output = formatArea(/** @type {ol.geom.Polygon} */(geom));//面积值
                      tooltipCoord = geom.getInteriorPoint().getCoordinates();//坐标
                  } else if (geom instanceof ol.geom.LineString) {
                      output = formatLength( /** @type {ol.geom.LineString} */(geom));//长度值
                      tooltipCoord = geom.getLastCoordinate();//坐标
                  }
                  _this.measure.measureTooltipElement.innerHTML = output;//将测量值设置到测量工具提示框中显示
                  _this.measure.measureTooltip.setPosition(tooltipCoord);//设置测量工具提示框的显示位置
              });
          }, this);
        //绑定交互绘制工具结束绘制的事件
        draw.on('drawend',
            function (evt) {
                _this.measure.measureTooltipElement.className = 'tooltip tooltip-static'; //设置测量提示框的样式
                _this.measure.measureTooltip.setOffset([0, -7]);
                // unset sketch
                sketch = null; //置空当前绘制的要素对象
                // unset tooltip so that a new one can be created
                _this.measure.measureTooltipElement = null; //置空测量工具提示框对象
                _this.createMeasureTooltip();//重新创建一个测试工具提示框显示结果
                ol.Observable.unByKey(listener);
            }, this);
        /**
        * 测量长度输出
        * @param {ol.geom.LineString} line
        * @return {string}
        */
        var formatLength = function (line) {
            var length;
            if (_this.measure.useGeodesic) { //若使用测地学方法测量
                var coordinates = line.getCoordinates();//解析线的坐标
                length = 0;
                var sourceProj = _this.map.getView().getProjection(); //地图数据源投影坐标系
                //通过遍历坐标计算两点之前距离，进而得到整条线的长度
                for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {
                    var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');
                    var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');
                    length += _this.wgs84Sphere.haversineDistance(c1, c2);
                }
            } else {
                length = Math.round(line.getLength() * 100) / 100; //直接得到线的长度
            }
            var output;
            if (length > 100) {
                output = (Math.round(length / 1000 * 100) / 100) + ' ' + 'km'; //换算成KM单位
            } else {
                output = (Math.round(length * 100) / 100) + ' ' + 'm'; //m为单位
            }
            return output;//返回线的长度
        };
        /**
        * 测量面积输出
        * @param {ol.geom.Polygon} polygon
        * @return {string}
        */
        var formatArea = function (polygon) {
            var area;
            if (_this.measure.useGeodesic) {//若使用测地学方法测量
                var sourceProj = _this.map.getView().getProjection();//地图数据源投影坐标系
                var geom = /** @type {ol.geom.Polygon} */(polygon.clone().transform(sourceProj, 'EPSG:4326')); //将多边形要素坐标系投影为EPSG:4326
                var coordinates = geom.getLinearRing(0).getCoordinates();//解析多边形的坐标值
                area = Math.abs(_this.wgs84Sphere.geodesicArea(coordinates)); //获取面积
            } else {
                area = polygon.getArea();//直接获取多边形的面积
            }
            var output;
            if (area > 10000) {
                output = (Math.round(area / 1000000 * 100) / 100) + ' ' + 'km<sup>2</sup>'; //换算成KM单位
            } else {
                output = (Math.round(area * 100) / 100) + ' ' + 'm<sup>2</sup>';//m为单位
            }
            return output; //返回多边形的面积
        };
	},
	/**
	 * 清除测量.
	 */
	clearMeasure:function(){
		this.map.removeInteraction(this.measure.draw);
		this.measure.draw = null;
		this.map.removeLayer(this.measure.layer);
		this.measure.layer = null;
		this.map.un('pointermove', this.measure.pointerMoveHandler,this);
		$(".tooltip").remove();
	},
	/**
	 * 计算地图上两个坐标点的距离.不限制地图投影坐标系
	 * 20180824雷志强
	 * @param {Object} coordinates1  坐标对象,格式为：[x,y];例如：[113.42,30.145]
	 * @param {Object} coordinates2  坐标对象,格式为：[x,y];例如：[113.42,30.145]
	 */
	getMapPointDistance:function(coordinates1,coordinates2){
		//获取地图数据源投影坐标系
		var sourceProj = this.map.getView().getProjection();
		var c1 = ol.proj.transform(coordinates1,sourceProj,'EPSG:4326');
		var c2 = ol.proj.transform(coordinates2,sourceProj,'EPSG:4326');
		return this.wgs84Sphere.haversineDistance(c1,c2);
	},
	
	/**
	 * 注册一次性鼠标事件
	 * @param {String} type 鼠标事件类型：click|dblclick|moveend|movestart|pointerdrag|pointermove|postcompose|postrender|precompose|singleclick
	 * @param {Function} callback 事件回调方法，类型为function
	 */
	addOnceEvent:function(type,callback){
		this.map.once(type, function (e) {
            var coordinate = e.coordinate;
            if(callback!=null && typeof(callback)=="function"){
            	callback(coordinate);
            }
        });
	},
	/**
	 * 注册鼠标事件，可执行多次，直达事件注销
	 * @param {String} type 鼠标事件类型，例如：click|dblclick|moveend|movestart|pointerdrag|pointermove|postcompose|postrender|precompose|singleclick
	 * @param {Function} callback 事件回调方法，类型为function
	 */
	addEvent:function(type,callback){
		this.map.on(type, function (e) {
            var coordinate = e.coordinate;
            if(callback!=null && typeof(callback)=="function"){
            	callback(coordinate);
            }
        });
	},
	/*****GPS历史轨迹动画显示功能封装开始*******/
	/**
	 * 显示GPS历史轨迹线.[方法已弃用]
	 * 20180828 雷志强
	 * @param {Object} points GPS历史轨迹线坐标点，格式x,y;x,y;x,y
	 * @param {Object} linestyle 绘制的轨迹线样式，可以为null，则显示默认样式
	 * @param {Object} iconFeature 模拟动画要素(汽车图标要素)
	 * @param {Object} speed 模拟动画车速(公里/小时)，最好是36以上
	 */
	showGpsHistoryLine:function(points,linestyle,iconFeature,speed){
		var _this = this;
		//创建矢量图层
		var layer = this.addVectorLayer("GPS历史轨迹");
		//设置图层顶层显示
		this.showLayerTop(layer);
		//将线坐标字符串转换成对象数组[{x:113,y:30}]
		var pntArr = this.pointstrToPointArray(points);
		//将坐标对象数组转换成地图的坐标格式[x,y];
		var geomPoints = this.pointArrayToGeomPoint(pntArr);
		//创建线要素对象
		var line = this.createLineFeature(geomPoints,linestyle);
		//将线要素对象添加到图层上显示
		this.addVectorFeature(layer,line);
        //初始化小车位置，显示在第一个点
       	if(geomPoints.length>0){
       		(iconFeature.getGeometry()).setCoordinates(geomPoints[0]);
       	}
       	if(geomPoints.length>1){
       		var jiaodu = this.getPointAngle(geomPoints[0][0],geomPoints[0][1],geomPoints[1][0],geomPoints[1][1]);
       		iconFeature.getStyle().getImage().setRotation((360-jiaodu)*Math.PI/180);
       	}
		this.addVectorFeature(layer,iconFeature);
		//将GPS历史轨迹点按间距进行加密
		var morePoints = this.getMorePointsByDistance(pntArr,this.gps_point_distance);
		//转换成地图上坐标格式
		var geomPoints = this.pointArrayToGeomPoint(morePoints);
		//存储相关参数及对象
		this.gpshistory.line = line;
		this.gpshistory.linepoints = pntArr;
		this.gpshistory.layer = layer;
		this.gpshistory.icon = iconFeature;
		this.gpshistory.geompoints = geomPoints;
		this.gpshistory.timespace = 100;
		this.gpshistory.speed = speed;
		var point_step = parseInt((this.gpshistory.timespace/1000)*speed*1000/3600,10);
		if(point_step==0){
			point_step = 1;
		}
		this.gpshistory.point_step = point_step;
		this.gpshistory.index = 0;
	},
	/**
	 * 初始化GPS历史轨迹.
	 * 20181009 雷志强
	 * @param {Array} points GPS历史轨迹线坐标点对象数组，格式[{x:113,y:30,cph:"鄂A88888",gpstime:"2018-10-09 12:00:00"},{...}]
	 * @param {ol.style} linestyle 绘制的轨迹线样式，可以为null，则显示默认样式
	 * @param {ol.Feature} iconFeature 模拟动画要素(汽车图标要素)，需要设置图标样式
	 * @param {Number} speed 模拟动画车速(公里/小时)，最好是36以上
	 * @param {Object} option 其他扩展参数对象，格式：{rotate:true},例如：设置图标是否转向,rotate:true-转向,false-不转向
	 */
	initGpsHistory:function(points,linestyle,iconFeature,speed,option){
		this.clearGpsHistory();
		var _this = this;
		//自定义默认参数，如果传入则自动替换
		var opt = {
			rotate:true
		};
		$.extend(true, opt, option);
		setTimeout(function(){
			//计算GPS坐标点外包矩形范围，以最佳方式显示
			var pointRect = _this.getPointsRect(points);
			_this.viewInRect([pointRect.xmin,pointRect.ymin,pointRect.xmax,pointRect.ymax]);
		},300);
		//创建矢量图层
		var layer = this.addVectorLayer("GPS历史轨迹");
		//设置图层顶层显示
		this.showLayerTop(layer);
		//将GPS历史轨迹点按间距进行加密
		var morePoints = this.getGpsHistoryMorePoints(points,this.gps_point_distance);
		//初始化小车位置，显示在第一个点
       	if(morePoints.length>0){
       		(iconFeature.getGeometry()).setCoordinates([morePoints[0].x,morePoints[0].y]);
       	}
       	//如果设置了图标角度转向则动态设置图标角度显示
       	if(opt.rotate){
       		if(morePoints.length>1){
	       		var jiaodu = this.getPointAngle(morePoints[0].x,morePoints[0].y,morePoints[1].x,morePoints[1].y);
	       		iconFeature.getStyle().getImage().setRotation((360-jiaodu)*Math.PI/180);
	       	}
       	}
		this.addVectorFeature(layer,iconFeature);
		//存储相关参数及对象
		//this.gpshistory.line = line;
		//this.gpshistory.linepoints = pntArr;
		this.gpshistory.linestyle = linestyle;
		this.gpshistory.layer = layer;
		this.gpshistory.icon = iconFeature;
		this.gpshistory.gpspoints = morePoints;
		this.gpshistory.timespace = 100;
		this.gpshistory.speed = speed;
		this.gpshistory.option = opt;
		var point_step = parseInt((this.gpshistory.timespace/1000)*speed*1000/3600,10);
		if(point_step==0){
			point_step = 1;
		}
		this.gpshistory.point_step = point_step;
		this.gpshistory.index = 0;
	},
	/**
	 * 根据距离加密GPS历史轨迹坐标点(同时计算模拟gps时间).
	 * 20181009 雷志强
	 * @param {Object} points GPS历史轨迹线坐标点对象数组，格式[{x:113,y:30,cph:"鄂A88888",gpstime:"2018-10-09 12:00:00"},{...}]
	 * @param {Object} distance 加密距离(单位：米)，值不能小于1
	 */
	getGpsHistoryMorePoints:function(points,distance){
		var newPoints = [];
		if(Array.isArray(points)){
			var pcount = points.length;
			var point1 = null;
			var point2 = null;
			var date1 = null;
			var date2 = null;
			var timespace = 0;
			var timestep = 0;
			for(var i=0;i<pcount-1;i++){
				point1 = points[i];
				point2 = points[i+1];
				date1 = dateUtil.dateString2Date(point1.gpstime);
				date2 = dateUtil.dateString2Date(point2.gpstime);
				timespace = date2.getTime() - date1.getTime();
				point1.x = parseFloat(point1.x);
				point1.y = parseFloat(point1.y);
				point2.x = parseFloat(point2.x);
				point2.y = parseFloat(point2.y);
				//计算两个点的距离
				var pntDistance = this.getDistance(point1.x,point1.y,point2.x,point2.y);
				//根据点之间的距离计算两个点之间要生成多少个点
				var line_point_count = parseInt(pntDistance/distance);
				timestep = timespace/line_point_count;
				//计算两个点的X坐标差
	    		var xdis = point2.x-point1.x;
	    		//计算两个点的Y坐标差
		    	var ydis = point2.y-point1.y;
		    	//计算加密后的每一个点的X值步长
		    	var posx = xdis/line_point_count;
		    	//计算加密后的每一个点的Y值步长
		    	var posy = ydis/line_point_count;
		    	var step_point = {};
		    	for(var k=0;k<line_point_count;k++){
		    		step_point = $.extend(true,{},point1);
		    		var px = point1.x+posx*k;
		    		var py = point1.y+posy*k;
		    		var ptime = date1.getTime() + timestep*k;
		    		step_point.x = px;
		    		step_point.y = py;
		    		step_point.gpstime = dateUtil.date2String("yyyy-MM-dd hh:mm:ss",new Date(ptime));
		    		newPoints.push(step_point);
		    	}
			}
			newPoints.push(point2);
		}else{
			console.log("points参数必须为对象数组，且格式为：[{x:123.4124,y:30.314,cph:'鄂A12345',gpstime:'2018-09-09 12:00:00'}]");
		}
		return newPoints;
	},
	/**
	 * GPS运动动画模拟(边运动边绘制轨迹线).
	 * 20181009 雷志强
	 */
	moveGpsFeature:function(){
		var _this = this;
		var opt = this.gpshistory.option;
		var point_step = this.gpshistory.point_step;
		var icon = this.gpshistory.icon;
		var points = this.gpshistory.gpspoints;
		var index = this.gpshistory.index;
		var linepoint1 = this.gpshistory.gpspoints[index];
		if((points.length - 1) > index){
			index = index + point_step;
			if(index >= points.length - 1){
				index = points.length - 1;
			}
			_this.gpshistory.index = index;
			var point = points[index];
			var line = this.createLineFeature([[linepoint1.x,linepoint1.y],[point.x,point.y]],this.createFeatureStyle(null));
			if(_this.gpshistory.linestyle!=null){
				line.setStyle(_this.gpshistory.linestyle);
			}
			this.addVectorFeature(this.gpshistory.layer,line);
			icon.getStyle().getText().setText(point.cph+point.gpstime);
			//如果设置了图标运动转向则将动态设置图标角度
			if(opt.rotate){
				var jiaodu = 0;
				if(points.length>1){
					if(index < (points.length-1)){
						var next_point = points[index+1];
						jiaodu = _this.getPointAngle(point.x,point.y,next_point.x,next_point.y);
					}else{
						jiaodu = _this.getPointAngle(points[index-1].x,points[index-1].y,points[index].x,points[index].y);
					}
				}
				icon.getStyle().getImage().setRotation((360-jiaodu)*Math.PI/180);
			}
			(icon.getGeometry()).setCoordinates([point.x,point.y]);
		}else{
			clearInterval(this.gpshistory.timetask);
		}
	},
	/**
	 * GPS运动动画模拟.[方法已弃用]
	 * 20180828 雷志强
	 */
	moveFeature:function(){
		var _this = this;
		var point_step = this.gpshistory.point_step;
		var icon = this.gpshistory.icon;
		var points = this.gpshistory.geompoints;
		var index = this.gpshistory.index;
		if((points.length - 1) > index){
			index = index + point_step;
			if(index >= points.length - 1){
				index = points.length - 1;
			}
			_this.gpshistory.index = index;
			var point = points[index];
			var jiaodu = 0;
			if(points.length>1){
				if(index < (points.length-1)){
					var next_point = points[index+1];
					jiaodu = _this.getPointAngle(point[0],point[1],next_point[0],next_point[1]);
				}else{
					jiaodu = _this.getPointAngle(points[index-1][0],points[index-1][1],points[index][0],points[index][1]);
				}
			}
			icon.getStyle().getImage().setRotation((360-jiaodu)*Math.PI/180);
			(icon.getGeometry()).setCoordinates(point);
		}else{
			clearInterval(this.gpshistory.timetask);
		}
	},
	/**
	 * 启动模拟动画.
	 * 20180828 雷志强
	 */
	startGpsHistoryAnimation:function(){
		var _this = this;
		this.pauseGpsHistoryAnimation();
		this.gpshistory.timetask = setInterval(function(){
			_this.moveGpsFeature();
		},this.gpshistory.timespace);
	},
	/**
	 * 暂时模拟动画.
	 * 20180828 雷志强
	 */
	pauseGpsHistoryAnimation:function(){
		clearInterval(this.gpshistory.timetask);
	},
	/**
	 * 加速模拟动画.
	 * 20180828 雷志强
	 */
	addGpsHistoryAnimationSpeed:function(){
		this.gpshistory.speed = this.gpshistory.speed*2;
		var point_step = parseInt((this.gpshistory.timespace/1000)*this.gpshistory.speed*1000/3600,10);
		if(point_step==0){
			point_step = 1;
		}
		this.gpshistory.point_step = point_step;
	},
	/**
	 * 减速模拟动画.
	 * 20180828 雷志强
	 */
	subtractGpsHistoryAnimationSpeed:function(){
		this.gpshistory.speed = this.gpshistory.speed/2;
		var point_step = parseInt((this.gpshistory.timespace/1000)*this.gpshistory.speed*1000/3600,10);
		if(point_step==0){
			point_step = 1;
		}
		this.gpshistory.point_step = point_step;
	},
	/**
	 * 清除GPS历史轨迹模拟动画.
	 * 20180828 雷志强
	 */
	clearGpsHistory:function(){
		this.pauseGpsHistoryAnimation();
		this.map.removeLayer(this.gpshistory.layer);
		this.gpshistory.index = 0;
	},
	/*****GPS历史轨迹动画显示功能封装结束*******/
	/*****GPS实时位置显示功能封装开始*******/
	/**
	 * 初始化GPS设备实时轨迹，在地图上添加GPS设备图标
	 * @param {Object} layer 图标要素矢量图层对象
	 * @param {String} gpsid GPS设备唯一标识，建议使用编号或者ID
	 * @param {Object} iconFeature GPS设备图标要素对象
	 * @param {Number} gpstime GPS点间隔时间(单位：秒)，例如：6
	 * @param {Boolean} isRotate 图标是否需要转换角度true-需要|不需要
	 */
	initNowGpsPoint:function(layer,gpsid,iconFeature,gpstime,isRotate){
		if(gpsid in this.gpsreal){
			layer.getSource().removeFeature(this.gpsreal[gpsid].icon);
			this.stopRealGpsTask(gpsid);
		}
		this.addVectorFeature(layer,iconFeature);
		var coordinate = iconFeature.getGeometry().flatCoordinates;
		var timespace = gpstime*1000/10;
		timespace = 100;
		console.log(timespace);
		var is_rotate = isRotate;
		if(typeof(is_rotate)==undefined || is_rotate==null){
			is_rotate = true;
		}
		this.gpsreal[gpsid]={
			layer:layer,//要素对应的图层
			icon:iconFeature,//图标要素
			index:0,//当前点的索引号
			point_step:0,//根据加密的点数和定时器间隔计算出点的索引步长
			gpstime:gpstime,//gps坐标点间隔时间
			timespace:timespace,//定时器间隔时间(单位：毫秒)
			timetask:null,//定时器对象，用于清除定时器
			points:[coordinate], //运行的点
			isRotate:is_rotate //运动中是否需要转换角度
		}
		this.startRealGpsTask(gpsid);
	},
	/**
	 * 启动GPS设备实时位置监听任务
	 * @param {String} gpsid GPS设备唯一标识，建议使用编号或者ID
	 */
	startRealGpsTask:function(gpsid){
		var _this = this;
		var gpsinfo = _this.gpsreal[gpsid];
		var timespace = gpsinfo.timespace;
		var point_step = gpsinfo.point_step;
		var icon = gpsinfo.icon;
		var points = gpsinfo.points;
		var index = gpsinfo.index;
		if((points.length - 1) > index){
			index = index + point_step;
			if(index >= points.length - 1){
				index = points.length - 1;
			}
			_this.gpsreal[gpsid].index = index;
			var point = points[index];
			//20180914新增判断：如果设置了需要转换角度才进行角度转换
			if(_this.gpsreal[gpsid].isRotate){
				var jiaodu = 0;
				if(points.length>1){
					if(index < (points.length-1)){
						var next_point = points[index+1];
						jiaodu = _this.getPointAngle(point[0],point[1],next_point[0],next_point[1]);
					}else{
						jiaodu = _this.getPointAngle(points[index-1][0],points[index-1][1],points[index][0],points[index][1]);
					}
				}
				icon.getStyle().getImage().setRotation((360-jiaodu)*Math.PI/180);
			}
			(icon.getGeometry()).setCoordinates(point);
		}
		clearTimeout(_this.gpsreal[gpsid].timetask);
		_this.gpsreal[gpsid].timetask = setTimeout(function(){
			_this.startRealGpsTask(gpsid);
		},timespace);
	},
	/**
	 * 更新实时GPS图标样式
	 * 20180914 雷志强
	 * @param {String} gpsid GPS设备唯一标识，建议使用编号或者ID
	 * @param {Object} style 要素样式对象，ol.style.Style
	 */
	setRealGpsIcon:function(gpsid,style){
		var _this = this;
		var gpsinfo = _this.gpsreal[gpsid];
		if("icon" in gpsinfo){
			var icon = gpsinfo.icon;
			if(icon!=null){
				icon.setStyle(style);
			}
		}
	},
	/**
	 * 设置GPS设备最新坐标点
	 * @param {String} gpsid GPS设备唯一标识，建议使用编号或者ID
	 * @param {Object} point 坐标点对象，例如：{x:113,y:30.415}
	 */
	setRealGpsPoint:function(gpsid,point){
		var _this = this;
		if(!(gpsid in this.gpsreal)){
			return;
		}
		var gpsinfo = _this.gpsreal[gpsid];
		var points = gpsinfo.points;
		var point_step = gpsinfo.point_step;
		var timespace = gpsinfo.timespace;
		var line_point = [];
		var last_point = points[points.length-1];
		line_point.push({x:last_point[0],y:last_point[1]});
		line_point.push(point);
		var more_points = _this.getMorePointsByDistance(line_point,1);
		var geom_points = _this.pointArrayToGeomPoint(more_points);
		_this.gpsreal[gpsid].points = points.concat(geom_points);
		var pointCount = _this.gpsreal[gpsid].points.length - gpsinfo.index;
		point_step = parseInt(pointCount/timespace);
		if(point_step<1){
			point_step = 1;
		}
		_this.gpsreal[gpsid].point_step = point_step;
	},
	/**
	 * 停止GPS设备实时位置监听任务
	 * @param {String} gpsid GPS设备唯一标识，建议使用编号或者ID
	 */
	stopRealGpsTask:function(gpsid){
		var _this = this;
		if(gpsid in this.gpsreal){
			clearTimeout(_this.gpsreal[gpsid].timetask);
			_this.gpsreal[gpsid].timetask = null;
		}
	},
	/**
	 * 清除GPS设备实时位置显示
	 * @param {String} gpsid GPS设备唯一标识，建议使用编号或者ID
	 */
	clearRealGps:function(gpsid){
		//先判断GPS设备是否存在，如果存在，则停止实时位置显示，同时移除访设备图标
		if(gpsid in this.gpsreal){
			this.stopRealGpsTask(gpsid);
			this.gpsreal[gpsid].layer.getSource().removeFeature(this.gpsreal[gpsid].icon);
			delete this.gpsreal[gpsid];
		}
	},
	/**
	 * 清除所有实时GPS设备要素
	 */
	clearAllRealGps:function(){
		var _this = this;
		for(var gpsid in this.gpsreal){
			_this.clearRealGps(gpsid);
		}
	}
	/*****GPS实时位置显示功能封装结束*******/
};
/***其他通用方法****/
/**
 * 判断数组是否包含该元素
 * @param {Object} obj 元素
 */
Array.prototype.contains = function (obj) {
	var i = this.length;
	while (i--) {
		if (this[i] === obj) {
			return true;
		}
	}
	return false;
}